﻿//////////////////////////////////////////////////////////////////////////////
//
//  Copyright © 1998-2024 Glodon Company Limited.  All rights reserved.
//
//  Use of this software is subject to the terms of the Glodon license
//  agreement provided at the time of installation or download, or which
//  otherwise accompanies this software in either electronic or hard copy form.  
//
//////////////////////////////////////////////////////////////////////////////

// Reviewed

#pragma once

#include "IPolygon.h"
#include "PolygonBoolResultIndexMap.h"
 
namespace gcmp
{
    class ICurve2d;

    class GCMP_GEOMETRY_INTERFACE_EXPORT IPolygonOperate
    {
    public:
        virtual ~IPolygonOperate() {}

        /// \brief 输入两个IPolygon, 进行交运算
        /// \param first                                 第一个IPolygon
        /// \param second                                第二个IPolygon
        /// \param resultGmPolygon                      返回的IPolygon
        /// \param polygonBoolResultIndexMapList        布尔运算前后coedge的对应关系(输入指针为空则不返回)
        virtual bool Intersect(const IPolygon* first, const IPolygon* second, OwnerPtr<IPolygon> &resultPolygon, std::vector<std::vector<PolygonBoolResultIndexMap>>* polygonBoolResultIndexMapList, double dDistanceEpsilon) const = 0;

         /// \brief 输入两个IPolygon, 进行并运算
         /// \param first 第一个IPolygon
         /// \param second 第二个IPolygon
         /// \param resultGmPolygon 返回的IPolygon
         /// \param polygonBoolResultIndexMapList        布尔运算前后coedge的对应关系(输入指针为空则不返回)
        virtual bool Unite(const IPolygon* first, const IPolygon* second, OwnerPtr<IPolygon> &resultPolygon, std::vector<std::vector<PolygonBoolResultIndexMap>>* pPolygonBoolResultIndexMapList, double dDistanceEpsilon) const = 0;


        
        /// \brief 输入两个IPolygon, 进行差运算
        /// \param first 第一个IPolygon
        /// \param second 第二个IPolygon
        /// \param resultGmPolygon 返回的IPolygon
        /// \param polygonBoolResultIndexMapList        布尔运算前后coedge的对应关系(输入指针为空则不返回)
        virtual bool Subtract(const IPolygon* first, const IPolygon* second, OwnerPtr<IPolygon> &resultPolygon, std::vector<std::vector<PolygonBoolResultIndexMap>>* pPolygonBoolResultIndexMapList, double dDistanceEpsilon) const = 0;

        /// \brief      给定网格线，返回所有的封闭多边形
        /// \param curve2dList 给定网格线
        /// \param eps 容差
        /// \param polygonList 搜到的多边形，保证多边形合法
        virtual bool SearchPolygons(const std::vector<const ICurve2d*> &curve2dList, double eps, std::vector<OwnerPtr<IPolygon>>& polygonList) const = 0;

        /// \brief 给定一组二维曲线，搜索包含point点的最小多边形
        /// \param[in] curve2dList 二维曲线数组
        /// \param[in] point 搜索的参照点
        /// \param[in] dDistanceEpsilon 距离容差
        /// \param[out] resultPolygon 返回的IPolygon
        /// \return 是否搜索成功，保证多边形合法，且point一定在多边形的内部（包含边上）
        virtual bool SearchPolygon(const std::vector<const ICurve2d*> &curve2dList, const Vector2d &point, double dDistanceEpsilon, OwnerPtr<IPolygon> &resultPolygon) const = 0;

        /// \brief 输入两个IPolygon, 进行合并运算
        /// \param first 第一个IPolygon
        /// \param second 第二个IPolygon
        /// \param resultGmPolygon 返回的IPolygon
        virtual bool Merge(const IPolygon* first, const IPolygon* second, OwnerPtr<IPolygon> &resultPolygon) const = 0;

        /// \brief   将Polygon拆成多个单连通的多边形
        /// \param[in] pPolygon    输入多边形
        /// \param[out] singleConnectedPolygons    单连通的多边形数组
        /// \param[out] loopIndexes    索引数组,每一个vector<int>按顺序对应singleConnectedPolygons里的元素
        ///                             vector<int>中的下标对应生成多边形的环索引,值对应原多边形的环索引
        /// \return  拆分成功返回True，失败返回False
        virtual bool CreateConnectedPolygon(const IPolygon* pPolygon, std::vector<OwnerPtr<IPolygon>> &singleConnectedPolygons, std::vector<std::vector<int>> &loopIndexes) const = 0;
    
        /// \brief 判断多边形是否需要修复
        /// \param pPolygon    输入多边形
        /// \param distanceEpsilon 距离容差，根据实际情况传入，一般传入0.1或根据图元精度来设置；
        /// 对于存在缝隙的多边形，传入的distanceEpsilon需大于缝隙的长度才能补缝，如果容差过小，
        /// 会导致成环失败，缝隙未能补上，若缝隙与极短边同时存在，删除极短边会导致缝隙扩大，
        /// 如果容差不合适导致求交结果不准确从而导致成环失败或修复结果不理想
        /// \param angleEpsilon 角度容差,用于修复过程中判断边是否平行,建议不要设置太大,参考系统角度容差值1e-3
        /// \return 需要修复返回true, 否则返回false
        /// \note 不合法情况，有缝隙，边重合，自交等
        virtual bool IsPolygonNeedRepair(const IPolygon * pPolygon, double distanceEpsilon, double angleEpsilon) const = 0;

        /// \brief 修复多边形,使其合法
        /// \param distanceEpsilon 距离容差，根据实际情况传入，一般传入0.1或根据图元精度来设置；
        /// 对于存在缝隙的多边形，传入的distanceEpsilon需大于缝隙的长度才能补缝，如果容差过小，
        /// 会导致成环失败，缝隙未能补上，若缝隙与极短边同时存在，删除极短边会导致缝隙扩大，
        /// 如果容差不合适导致求交结果不准确从而导致成环失败或修复结果不理想
        /// \param angleEpsilon 角度容差,用于修复过程中判断边是否平行,建议不要设置太大,参考系统角度容差值1e-3
        /// \return 修复成功，返回修复后的多边形, 否则返回空指针
        /// \note 不合法情况，有缝隙，边重合，自交等； 需要先调用IsPolygonNeedRepair
        virtual OwnerPtr<IPolygon> RepairPolygon(const IPolygon * pPolygon, double distanceEpsilon, double angleEpsilon) const = 0;

        /// \brief  给定一组二维曲线，搜索所有外轮廓多边形
        ///
        /// 建议距离容差设置小于等于0.1,若该容差设置过大，会影响求交精度，可能导致求交结果不准确，而导致搜环结果不是用户期望的结果。请合理设置距离容差！！！
        ///
        /// \param pCurve2dList        二维曲线数组
        /// \param dDistanceEpsilon    距离容差
        /// \param[out] opPolygonList  搜到的所有外轮廓多边形,保证多边形合法
        /// \return 成功返回true，失败返回false
        virtual bool SearchOutPolygons(const std::vector<const ICurve2d*> &pCurve2dList, double dDistanceEpsilon, std::vector<OwnerPtr<IPolygon>>& opPolygonList) const = 0;
        
        /// \brief 输入一个多边形和一个多边形数组，查找多边形数组中与这个多边形全等的多边形
        ///
        /// \param[in] pPolygon 输入的一个多边形
        /// \param[in] polygonArray 输入的多边形数组
        /// \param[out] 与输入多边形全等的多边形的索引和对应的变换矩阵
        /// \param[in] dDistanceEpsilon    距离容差
        /// \param[out] errorIndexArray 非法 Polygon（无法提取特征） 的索引
        /// \return 无非法情况，返回true。其他情况返回false，输出的全等多边形信息可用
        virtual bool SearchCongruentPolygons(const IPolygon* pPolygon, const std::vector<const IPolygon*>& polygonArray, std::vector<std::pair<int, Matrix4d>>& indexAndMatrix4d, double dDistanceEpsilon, std::vector<int>* errorIndexArray) const = 0;

        /// \brief 输入一组多边形，将其中全等的多边形分类
        ///
        /// \param[in] polygonArray 输入的一组多边形
        /// \param[out] 分类的结果。输出结果是一个数组，数组中每个元素都代表一种全等多边形。
        /// 每个元素的第一个参数是这种全等多边形在输入的多边形数组中第一次出现的索引。
        /// 每个元素的第二个参数是其他全等多边形的索引和变换矩阵。
        /// \param[in] dDistanceEpsilon    距离容差
        /// \param[out] errorIndexArray 非法 Polygon（无法提取特征）的索引
        /// \return 无非法情况，返回true。其他情况返回false，输出的全等多边形信息可用
        virtual bool ClassifyCongruentPolygons(const std::vector<const IPolygon*>& polygonArray, std::vector<std::pair<int, std::vector<std::pair<int, Matrix4d>>>>& classification, double dDistanceEpsilon, std::vector<int>* errorIndexArray) const = 0;

        /// \brief 输入一组多边形，判断多边形是否重叠
        ///
        /// \param[in] polygonArray 输入的一组多边形
        /// \param[out] isOverlaped 是否重叠。
        /// \param[in] dDistanceEpsilon    距离容差
        /// \param[out] indexOverlaped 重叠的结果。输出结果是一个数组，数组中每个元素都代表一组重叠多边形。
        /// \param[out] errorIndexArray 非法 Polygon的索引
        /// \return 无非法情况，返回true。其他情况返回false，输出的信息可用
        virtual bool SearchOverlapedPolygon(const std::vector<const IPolygon*>& polygonArray, bool& isOverlaped, double dDistanceEpsilon, std::vector<std::pair<int, int>>* indexOverlaped, std::vector<int>* errorIndexArray) const = 0;

        /// \brief 输入一个多边形和一个多边形数组，判断目标多边形是否与多边形数组重叠
        ///
        /// \param[in] pPolygon 输入的一个多边形
        /// \param[in] polygonArray 输入的一组多边形
        /// \param[out] isOverlaped 是否重叠。
        /// \param[in] dDistanceEpsilon    距离容差
        /// \param[out] indexOverlaped 重叠的结果。输出结果是一个数组，数组中每个元素都代表一组重叠多边形。
        /// \param[out] errorIndexArray 非法 Polygon的索引
        /// \return 无非法情况，返回true。其他情况返回false，输出的信息可用
        virtual bool SearchOverlapedPolygon(const IPolygon* pPolygon, const std::vector<const IPolygon*>& polygonArray, bool& isOverlaped, double dDistanceEpsilon = Constants::LENGTH_EPS, std::vector<int>* indexOverlaped = nullptr, std::vector<int>* errorIndexArray = nullptr) const = 0;
    };
}
